using System;
using Microsoft.Win32.SafeHandles;
using System.Net;

namespace InfiniTec.DirectoryServices
{
    class AuthenticationSafeHandle: SafeHandleZeroOrMinusOneIsInvalid
    {
        public AuthenticationSafeHandle(): base(true)
        {

        }

        protected override bool ReleaseHandle()
        {
            SafeNativeMethods.DsFreePasswordCredentials(handle);

            return true;
        }

        public static AuthenticationSafeHandle Create(NetworkCredential credential)
        {
            AuthenticationSafeHandle handle;
            uint result;

            if (credential == null)
            {
                result = SafeNativeMethods.DsMakePasswordCredentials(null, null, null, out handle);
            }
            else
            {
                result = SafeNativeMethods.DsMakePasswordCredentials(credential.UserName, credential.Domain,
                    credential.Password, out handle);
            }
            if (result != SafeNativeMethods.Success)
            {
                switch (result)
                {
                    case SafeNativeMethods.InvalidParameter: throw new InvalidOperationException(string.Format("The specified user was invalid ({0})", GetUsername(credential)));
                    case SafeNativeMethods.OutOfMemory: throw new OutOfMemoryException("Not enough memory");
                    default: throw new InvalidOperationException(string.Format("An unknown error while creating authentication handle (Error #{0})", result));
                }
            }
            return handle;
        }

        private static string GetUsername(NetworkCredential credential)
        {
            return (string.IsNullOrEmpty(credential.Domain) ? credential.UserName : credential.Domain + "\\" + credential.UserName);
        }
    }
}
